/////////////////////////////////////////////////////////////////////////////
// Purpose:     Runtime exceptions with logging capabilities
// Author:      Jesus Gonzalez
// Modified by:
// Copyright:   (c) 2003-2013 Jesus Gonzalez <jgonzalez@gdr-sistemas.com>
// License:     BSD License
/////////////////////////////////////////////////////////////////////////////

#ifndef _SMARTLIB_EXCEPTIONS_H_
#define _SMARTLIB_EXCEPTIONS_H_

/**
 * \file
 * Runtime exceptions with logging capabilities.
 */

#include <stdexcept>

/**
 * The RuntimeError class represents errors that are detected while a program
 * executes.
 *
 * It's an extension of the STL \p runtime_error class, with addition functionalities
 * to take advantage of the SmartLib logging subsystem.
 *
 * To throw runtime errors it's recommended to use the utility macros
 * #THROW_ERROR / #THROW_ERROR_LOG.
 *
 * @par Example
 * @code{.cpp}
 * try
 * {
 *    int errorCode = someFunction();
 *
 *    if( errorCode != 0 )
 *    {
 *        THROW_ERROR( "someFuntion() returned the error code '%d'", errorCode );
 *    }
 * }
 * catch( RuntimeError &e )
 * {
 *     e.Log();
 * }
 *
 * @endcode
 *
 * @see Log
 */
class RuntimeError : public std::runtime_error
{
public:
    /**
     * Default constructor.
     *
     * If \a log_on_throw is \p true, the error is logged immediately. Otherwise, the
     * error will only be logged by explicitly calling @ref Log() or if the
     * exception is not caught.
     *
     * @remarks
     * To throw runtime errors it's recommended to use the utility macros
     * #THROW_ERROR / #THROW_ERROR_LOG rather than constructing "manually" one of these
     * objects.
     *
     * @param[in] category Category of the error message (may be NULL)
     * @param[in] function Name of the function or method where the error is thrown
     * @param[in] msg Textual description of the error
     * @param[in] log_on_throw If \p true, the error is logged immediately
     */
	RuntimeError( const char* category,
	              const char* function,
	              std::string msg,
	              bool log_on_throw );

	/**
	 * Destructor.
	 */
	virtual ~RuntimeError() throw() {}

	/**
	 * Logs the error.
	 *
	 * Errors can only be logged once; calling this method more than once or
	 * if the message was logged when thrown is just ignored.
	 */
	void Log() const;

	/**
	 * Returns the category of the error message.
	 */
	std::string GetCategory() const { return m_category; }

    /**
     * Returns the name of the function or method where the error was thrown.
     */
	std::string GetFunction() const { return m_function; }

    /**
     * Returns the textual description of the error.
     */
	std::string GetMessage() const { return what(); }

private:
	std::string m_category;
	std::string m_function;
	bool m_logged;
};

#endif // _SMARTLIB_EXCEPTIONS_H_
